package com.aaron.spring;

import com.aaron.annotation.RpcScan;
import com.aaron.annotation.RpcService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.stereotype.Component;

/**
 * scan and filter specified annotations
 * 扫描和筛选指定的注解,手动注册bean.
 * 参考：https://www.jianshu.com/p/2b993ced6a4c
 */
@Slf4j
public class CustomScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    private static final String SPRING_BEAN_BASE_PACKAGE = "com.aaron";
    private static final String BASE_PACKAGE_ATTRIBUTE_NAME = "basePackage";
    // 资源接口
    private ResourceLoader resourceLoader;

    // 获取spring中的一些元数据
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    // 动态置顶扫描包路径下特殊的类加载到Bean中,重写的是ImportBeanDefinitionRegistrar接口。

    /**
     * 但是有一个问题，我们并不知道需要register哪些bean。
     * 这里我们还需要借助一个类ClassPathBeanDefinitionScanner，也就是扫描器，通过扫描器获取我们需要注册的bean.(CustomScanner.java)
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        // 获取@RpcScan注释的属性和值。AnnotationAttributes类似于map集合，
        AnnotationAttributes rpcScanAnnotationAttributes = AnnotationAttributes.fromMap(annotationMetadata.getAnnotationAttributes(RpcScan.class.getName()));
        String[] rpcScanBasePackages = new String[0];
        if (rpcScanAnnotationAttributes != null) {
            // 获取basePackage的属性的值,之前就是这样使用的@RpcScan(basePackage = {"github.javaguide"})。作为一个String数组输出
            rpcScanBasePackages = rpcScanAnnotationAttributes.getStringArray(BASE_PACKAGE_ATTRIBUTE_NAME);
        }
        if (rpcScanBasePackages.length == 0) {
            rpcScanBasePackages = new String[]{((StandardAnnotationMetadata) annotationMetadata).getIntrospectedClass().getPackage().getName()};
        }

        // 使用自定义的CustomScanner类，扫描注解
        // 自定义的CustomScanner()构造器,扫描@RpcService注解
        CustomScanner rpcServiceScanner = new CustomScanner(beanDefinitionRegistry, RpcService.class);
        // 自定义的CustomScanner()构造器,扫描@Component注解
        CustomScanner springBeanScanner = new CustomScanner(beanDefinitionRegistry, Component.class);

        // 资源接口不为空就赋值，调用ClassPathScanningCandidateComponentProvider中的方法
        if (resourceLoader != null) {
            rpcServiceScanner.setResourceLoader(resourceLoader);
            springBeanScanner.setResourceLoader(resourceLoader);
        }

        // 调用CustomScanner的scan方法，扫描到的包的数量
        int springBeanAmount = springBeanScanner.scan(SPRING_BEAN_BASE_PACKAGE);
        log.info("springBeanScanner扫描的数量 [{}]", springBeanAmount);

        // 调用CustomScanner的scan方法，扫描到的包的数量
        int rpcServiceCount = rpcServiceScanner.scan(rpcScanBasePackages);
        log.info("rpcServiceScanner扫描的数量 [{}]", rpcServiceCount);

    }

}
